package com.jh.comm;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.neovisionaries.ws.client.HostnameUnverifiedException;
import com.neovisionaries.ws.client.OpeningHandshakeException;
import com.neovisionaries.ws.client.StatusLine;
import com.neovisionaries.ws.client.WebSocket;
import com.neovisionaries.ws.client.WebSocketAdapter;
import com.neovisionaries.ws.client.WebSocketException;
import com.neovisionaries.ws.client.WebSocketFactory;
import com.neovisionaries.ws.client.WebSocketFrame;

public class WSManager {
    private static final String TAG = "WSManager";

    private static final int TIME_OUT = 15000;

    private static WebSocketFactory factory = new WebSocketFactory().setConnectionTimeout(TIME_OUT);

    private WSManager.WebSocketThread webSocketThread;

    private WebSocket webSocket;

    private boolean stop = false;

    private String SERVER = null;

    /**
     * 设置、获取服务器地址
     */
    public String getSERVER() {
        return SERVER;
    }

    public void setSERVER(String sERVER) {
        SERVER = sERVER;
    }

    /**
     * 0-未连接 1-正在连接 2-已连接
     */
    private int connectStatus = 0;// 是否已连接

    public void onCreate() {

        connectStatus = 0;
        webSocketThread = new WSManager.WebSocketThread();
        webSocketThread.start();

        System.out.println("onCreated");
    }

    public void onDestroy() {
        stop = true;
        webSocket.disconnect();
        webSocket.flush();
        webSocket = null;
        connectStatus = 0;
        System.out.println("onDestroy");
    }

    /**
     * 连接成功发送 WebSocketConnectedEvent 事件， 请求成功发送 CommonResponse 事件， 请求失败发送
     * WebSocketSendDataErrorEvent 事件。
     */
    private class WebSocketThread extends Thread {
        @Override
        public void run() {
            System.out.println("WebSocketThread->run()");
            setupWebSocket();
        }
    }

    private void setupWebSocket() {
        if (connectStatus != 0)
            return;
        connectStatus = 1;
        try {
            webSocket = factory.createSocket(getSERVER());
            webSocket.addListener(new WebSocketAdapter() {
                @Override
                public void onTextMessage(WebSocket websocket, String text) throws Exception {
                    super.onTextMessage(websocket, text);

                    System.out.println("onTextMessage->" + text);

                }

                @Override
                public void onTextMessageError(WebSocket websocket, WebSocketException cause, byte[] data)
                        throws Exception {
                    super.onTextMessageError(websocket, cause, data);
                    System.out.println("onTextMessageError()" + cause);
                }

                @Override
                public void onDisconnected(WebSocket websocket, WebSocketFrame serverCloseFrame,
                        WebSocketFrame clientCloseFrame, boolean closedByServer) throws Exception {
                    super.onDisconnected(websocket, serverCloseFrame, clientCloseFrame, closedByServer);
                    System.out.println("onDisconnected()");
                    connectStatus = 0;
                    if (!stop) {
                        // 断开之后自动重连
                        setupWebSocket();
                    }
                }

                @Override
                public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
                    super.onConnected(websocket, headers);
                    System.out.println("onConnected()");
                    connectStatus = 2;
                }
            });

            try {
                webSocket.connect();
            } catch (NullPointerException e) {
                connectStatus = 0;
                System.out.println("NullPointerException()-> " + e.getMessage());
                System.out.println("NullPointerException()");
            } catch (OpeningHandshakeException e) {
                connectStatus = 0;
                System.out.println(String.format("OpeningHandshakeException()->%s", e.getMessage()));
                System.out.println("OpeningHandshakeException()");
                StatusLine sl = e.getStatusLine();
                System.out.println("=== Status Line ===");
                System.out.println("=== Status Line ===");
                System.out.println(String.format("HTTP Version  = %s\n", sl.getHttpVersion()));
                System.out.println(String.format("HTTP Version  = %s\n", sl.getHttpVersion()));
                System.out.println(String.format("Status Code   = %s\n", sl.getStatusCode()));
                System.out.println(String.format("Status Code   = %s\n", sl.getStatusCode()));
                System.out.println(String.format("Reason Phrase = %s\n", sl.getReasonPhrase()));
                System.out.println(String.format("Reason Phrase = %s\n", sl.getReasonPhrase()));

                Map<String, List<String>> headers = e.getHeaders();
                System.out.println("=== HTTP Headers ===");
                System.out.println("=== HTTP Headers ===");
                for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
                    // Header name.
                    String name = entry.getKey();

                    // Values of the header.
                    List<String> values = entry.getValue();

                    if (values == null || values.size() == 0) {
                        // Print the name only.
                        System.out.println(name);
                        continue;
                    }

                    for (String value : values) {
                        // Print the name and the value.
                        System.out.println(String.format("%s: %s\n", name, value));
                        System.out.println(String.format("%s: %s\n", name, value));
                    }
                }
            } catch (HostnameUnverifiedException e) {
                connectStatus = 0;
                // The certificate of the peer does not match the expected
                // hostname.
                System.out.println(String.format("HostnameUnverifiedException()->%s", e.getMessage()));
                System.out.println("HostnameUnverifiedException()");
            } catch (WebSocketException e) {
                connectStatus = 0;
                // Failed to establish a WebSocket connection.
                System.out.println("WebSocketException()->" + e.getMessage());
                System.out.println("WebSocketException()");
            }
        } catch (IOException e) {
            connectStatus = 0;
            System.out.println("IOException()->" + e.getMessage());
            System.out.println("IOException()");
        }
    }// setupWebSocket

    public void sendText(String text) {
        if (text.isEmpty())
            return;
        System.out.println("sendText()-> " + text);

        if (webSocket != null && connectStatus == 2) {
            webSocket.sendText(text);
        }
    }

    public int getConnectStatus() {
        return connectStatus;
    }

    public void reconnect() {
        System.out.println("reconnect()");
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("reconnect()->begin restart...");
                try {
                    Thread.sleep(200);
                } catch (Exception e) {
                    System.out.println("reconnect()->run: ");
                }
                if (webSocketThread != null && !webSocketThread.isAlive()) {
                    connectStatus = 0;
                    webSocketThread = new WebSocketThread();
                    webSocketThread.start();
                    System.out.println("reconnect()->start success");
                } else {
                    System.out.println("reconnect()->start failed: webSocketThread==null || webSocketThread.isAlive()");
                }
            }
        }).start();
    }

    public void stop() {
        System.out.println("stop()");
        webSocket.disconnect();
        stop = true;
        System.out.println("stop()->success");
    }

}
